#pragma once
#include<etcd/Client.hpp>
#include<etcd/KeepAlive.hpp>
#include<etcd/Response.hpp>
#include<etcd/SyncClient.hpp>
#include<etcd/Value.hpp>
#include<etcd/Watcher.hpp>
#include<unistd.h>
#include<iostream>
#include"logger.hpp"

//服务注册类
class Registrant{
    public:
    using Ptr=std::shared_ptr<Registrant>;
    Registrant(const std::string&host)
    :_client(std::make_shared<etcd::Client>(host))
    ,_keep_alive(_client->leasekeepalive(3).get())
    ,_lease_id(_keep_alive->Lease()){
    }
    bool registrant(const std::string&key,const std::string&val){
        auto resp = _client->add(key, val, _lease_id).get(); // 添加一个用户服务，设置公约
        if (resp.is_ok() == false){
            LOG_ERROR("注册失败: {}",resp.error_message());
            return false;
        }
        return true;
    }
    ~Registrant(){
        _keep_alive->Cancel();
    }
    private:
    std::shared_ptr<etcd::Client> _client;
    std::shared_ptr<etcd::KeepAlive> _keep_alive;//租约对象
    uint64_t _lease_id;//租约id
};

//服务发现客户端类
class Discovery{
    public:
    using Ptr=std::shared_ptr<Discovery>;
    using NotifyCallback=std::function<void(const std::string&,const std::string&)>;
    Discovery(const std::string&host,const std::string&basedir,const NotifyCallback&put_cb,const NotifyCallback&del_cb)
    :_client(std::make_shared<etcd::Client>(host))
    ,_put_cb(put_cb)
    ,_del_cb(del_cb){
        //先进行服务发现，获取已有的数据
        auto resp=_client->ls(basedir).get();
        if(resp.is_ok()==false){
            LOG_ERROR("获取服务信息数据失败：{}",resp.error_message());
            return;
        }
        int sz=resp.keys().size();
        for(int i=0;i<sz;i++){
            if(_put_cb)_put_cb(resp.key(i),resp.value(i).as_string());
        }
        //然后进行事件监控，监控数据变化调用回调处理
        _watcher=std::make_shared<etcd::Watcher>(host,basedir,std::bind(&Discovery::CallBack,this,std::placeholders::_1),true);
    }
    ~Discovery(){
        LOG_DEBUG("!!!!!!");
        if(_watcher){
            LOG_DEBUG("。。。。。。。");
            _watcher->Cancel();
        }
    }
    private:
    void CallBack(const etcd::Response&resp){
        if(resp.is_ok()==false){
            LOG_ERROR("收到了一个错误事件通知：{}",resp.error_message());
            return;
        }
        for(auto const&ev : resp.events()){
            if(ev.event_type()==etcd::Event::EventType::PUT){
                LOG_DEBUG("新增服务：{}-{}",ev.kv().key(),ev.kv().as_string());
                _put_cb(ev.kv().key(),ev.kv().as_string());
            }
            else if(ev.event_type()==etcd::Event::EventType::DELETE_){
                LOG_DEBUG("服务下线：{}-{}",ev.kv().key(),ev.kv().as_string());
                _del_cb(ev.kv().key(),ev.kv().as_string());
            }
        }
    }
    NotifyCallback _put_cb;
    NotifyCallback _del_cb;
    std::shared_ptr<etcd::Client> _client;
    std::shared_ptr<etcd::Watcher> _watcher;
};